/**
 * 
 */
package jmotioncapture.testing.framework;

import java.util.Vector;

import jmotioncapture.camera.Frame;
import jmotioncapture.geometry2D.Point;

/**
 * @author Kenneth Lo
 * 
 */
public class PointCaptureTimer implements Runnable {

	/**
	 * GUI variable - Parent application
	 */
	final private TestingPanel parent;

	/**
	 * For <code>type</code> = 1: <code>captureDuration</code>
	 * <p>
	 * For <code>type</code> = 2: <code>numberOfPoint</code>
	 * <p>
	 * For <code>type</code> = 3:
	 * <code>mouseMotionParaNoOfFrameTextField</code>
	 * <p>
	 * For <code>type</code> = 4:
	 * <code>mouseMotionParaNoOfFrameTextField</code>
	 * <p>
	 * For <code>type</code> = 5: <code>numberOfPoint</code>
	 * <p>
	 */
	private int typeValue = 0;

	/**
	 * For <code>type</code> = 4: <code>mutilPointTrackingNumTextField</code>
	 * <p>
	 * For <code>type</code> = 5: <code>mutilPointTrackingNumTextField</code>
	 */
	private int typeValue2 = 0;

	/**
	 * 1: Single Point + Mouse Motion + Period of Time
	 * <p>
	 * 2: Single Point + Mouse Click
	 * <p>
	 * 3: Single Point + Mouse Motion + Number of point
	 * <p>
	 * 4: Mutil Point + Mouse Motion + Number of Point
	 * <p>
	 * 5: Mutil Point + Mouse Click
	 */
	private int type = 1;

	/**
	 * Create the thread stroing the point with specific <code>type</code> and
	 * <code>typeValue</code>. For type 4 and 5, need to use the constrcutor
	 * with 2 type value.
	 * 
	 * @param parent
	 *            Parent GUI
	 * @param typeValue
	 *            specific value for defined type
	 * @param type
	 *            1: Single Point + Mouse Motion + Period of Time
	 *            <p>
	 *            2: Single Point + Mouse Click
	 *            <p>
	 *            3: Single Point + Mouse Motion + Number of point
	 *            <p>
	 *            4: Mutil Point + Mouse Motion + Number of Point
	 *            <p>
	 *            5: Mutil Point + Mouse Click
	 * 
	 */
	public PointCaptureTimer(TestingPanel parent, int typeValue, int type) {
		this.parent = parent;
		this.typeValue = typeValue;
		this.type = type;
	}

	/**
	 * Create the thread stroing the point with specific <code>type</code> and
	 * <code>typeValue</code>. For type 1, 2 and 3, need to use the
	 * constrcutor with 1 type value.
	 * 
	 * @param parent
	 *            Parent GUI
	 * @param typeValue
	 *            specific value for defined type
	 * @param typeValue2
	 * @param type
	 *            1: Single Point + Mouse Motion + Period of Time
	 *            <p>
	 *            2: Single Point + Mouse Click
	 *            <p>
	 *            3: Single Point + Mouse Motion + Number of point
	 *            <p>
	 *            4: Mutil Point + Mouse Motion + Number of Point
	 *            <p>
	 *            5: Mutil Point + Mouse Click
	 */
	public PointCaptureTimer(TestingPanel parent, int typeValue,
			int typeValue2, int type) {
		this.parent = parent;
		this.typeValue = typeValue;
		this.typeValue2 = typeValue2;
		this.type = type;
	}

	/**
	 * Get the {@link jmotioncapture.geometry2D.Point} from parent GUI and add
	 * to current frames
	 * 
	 */
	private void addFirstPointToFrame() {

		// Get the current
		Point pt = this.parent.currentPoint;

		// Insert the current point into a vector
		Vector<Point> pts = new Vector<Point>(10, 10);
		pts.add(new Point(pt.getX(), pt.getY(), (short) 1));

		// Add frame to frames
		this.parent.frames.addFrame(new Frame(pts, System.currentTimeMillis()));

		// Update the GUI
		this.parent.pointListModel.addElement(pt.getX() + "," + pt.getY());
	}

	/**
	 * Get the {@link jmotioncapture.geometry2D.Point} from parent GUI and add
	 * to current frames with specific index
	 * 
	 * @param index
	 *            where to insert the new frame.
	 */
	private void appendPointToFrames(int index) {

		// Get the current
		Point pt = this.parent.currentPoint;

		// Add the vector to the Frame
		Frame frameGeo = this.parent.frames.frameAt(index);
		frameGeo.addPoint(new Point(pt.getX(), pt.getY(), (short) (frameGeo
				.getNumberOfPoints() + 1)));

		// Update the GUI
		this.parent.pointListModel.addElement(pt.getX() + "," + pt.getY());
	}

	/**
	 * 
	 * @param isFirstFrame
	 * @param index
	 */
	private void addMutilPointToFrame(boolean isFirstFrame, int index) {

		if (isFirstFrame)
			addFirstPointToFrame();
		else {
			appendPointToFrames(index);
		}
	}

	/**
	 * Start the thread
	 */
	public void run() {

		// Type 1: Single Point + Mouse Motion + Period of Time
		// Type 2: Single Point + Mouse Click
		// Type 3: Single Point + Mouse Motion + Number of point
		// Type 4: Mutil Point + Mouse Motion + Number of Point
		// Type 5: Mutil Point + Mouse Click

		if (type == 1 || type == 2 || type == 3) {
			for (int i = 3; i > 0; i--) {
				this.parent.dataTextArea.append("Start in " + i + " seconds\n");
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {

				}
			}
		}

		this.parent.isCaptureStart = true;
		this.parent.dataTextArea.append("Started\n");
		this.parent.dataLabel.setText("Started");

		if (type == 1) {

			long captureTime = System.currentTimeMillis();

			while ((System.currentTimeMillis() - captureTime) <= typeValue) {

				// Add the current to Frames
				addFirstPointToFrame();

				try {
					Thread.sleep(this.parent.interval);
				} catch (InterruptedException e) {

				}

				// Update the path
				this.parent.displayButton_Click(false);

			}

		} else if (type == 2) {
			String temp0 = this.parent.coordinatesLabel.getText();
			String temp1 = "";

			for (int i = 0; i < typeValue; i++) {
				boolean capturePoint = false;

				while (!capturePoint) {
					temp1 = this.parent.coordinatesLabel.getText();
					if (!temp0.equalsIgnoreCase(temp1)) {

						// Add the current to Frames
						addFirstPointToFrame();

						capturePoint = true;
						temp0 = temp1;

						this.parent.displayButton_Click(false);
					}
				}
			}
		} else if (type == 3) {
			while (this.parent.frames.size() < typeValue) {

				// Add the current to Frames
				addFirstPointToFrame();

				try {
					Thread.sleep(this.parent.interval);
				} catch (InterruptedException e) {

				}
				this.parent.displayButton_Click(false);

			}
		} else if (type == 4) {

			boolean isFirstFrame = true;

			for (int i = 0; i < typeValue2; i++) {

				for (int k = 2; k > 0; k--) {
					this.parent.dataTextArea.append("Line " + (i + 1)
							+ " Start in " + k + " seconds\n");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {

					}
				}

				this.parent.dataTextArea.append("Start!!\n");

				this.parent.pointListModel.addElement("Frame " + (i + 1));

				for (int j = 0; j < typeValue; j++) {

					// Add the current to Frames
					addMutilPointToFrame(isFirstFrame, j);
					try {
						Thread.sleep(this.parent.interval);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					this.parent.displayButton_Click(false);
				}

				isFirstFrame = false;
			}
		} else if (type == 5) {

			boolean isFirstFrame = true;

			for (int i = 0; i < typeValue2; i++) {

				this.parent.dataTextArea.append("Please input points for Line "
						+ (i + 1) + "\n");

				this.parent.pointListModel.addElement("Line " + (i + 1));

				String temp0 = this.parent.coordinatesLabel.getText();
				String temp1 = "";

				for (int j = 0; j < typeValue; j++) {
					boolean capturePoint = false;

					while (!capturePoint) {
						temp1 = this.parent.coordinatesLabel.getText();
						if (!temp0.equalsIgnoreCase(temp1)) {

							// Add the current to Frames
							addMutilPointToFrame(isFirstFrame, j);

							capturePoint = true;
							temp0 = temp1;

							this.parent.displayButton_Click(false);
						}
					}
				}
				isFirstFrame = false;
			}
		}

		this.parent.isCaptureStart = false;
		this.parent.dataTextArea.append("Finished\n");
		this.parent.dataLabel.setText("Finished");
		this.parent.dataTextArea.append("# of frames: "
				+ this.parent.frames.size() + "\n");
		this.parent.refreshTable();
	}

}
